package com.mxl.service.channel.adapter.impl;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mxl.common.StringUtil;
import com.mxl.common.helper.InterfaceType;
import com.mxl.common.helper.OrderStatus;
import com.mxl.common.helper.ResultStatus;
import com.mxl.dao.channel.ChannelGatewayRelationDao;
import com.mxl.dao.channel.DealRequestDao;
import com.mxl.dao.channel.DealResponseDao;
import com.mxl.dao.channel.model.ChannelGatewayRelation;
import com.mxl.dao.channel.model.DealRequest;
import com.mxl.dao.channel.model.DealResponse;
import com.mxl.service.channel.ChannelAccessor;
import com.mxl.service.channel.CommChannelAccessor;
import com.mxl.service.channel.CommDealRequestWrapper;
import com.mxl.service.channel.DealRequestWrapper;
import com.mxl.service.channel.adapter.ChargeService;
import com.mxl.service.channel.comm.CommStatusProcess;
import com.mxl.service.channel.strategy.ChannelResponseParseStrategy;
import com.mxl.service.dto.ChargeRequest;
import com.mxl.service.dto.ChargeResponse;

public class ChargeServiceImpl implements ChargeService {
	private static final Logger logger = LoggerFactory
			.getLogger(ChargeServiceImpl.class);
	// 渠道访问服务
	private ChannelAccessor channelAccessor;
	// 交易请求包装服务
	private DealRequestWrapper dealRequestWrapper;
	// 交易请求dao
	@Resource(name = "dealRequestDao")
	private DealRequestDao dealRequestDao;
	// 交易响应dao
	@Resource(name = "dealResponseDao")
	private DealResponseDao dealResponseDao;

	@Resource(name = "commStatusProcess")
	private CommStatusProcess commStatusProcess;

	@Resource(name = "channelGatewayRelationDao")
	private ChannelGatewayRelationDao channelGatewayRelationDao;

	private Map<String, ChannelResponseParseStrategy> channelStrategyMap;

	public void setChannelAccessor(ChannelAccessor channelAccessor) {
		this.channelAccessor = channelAccessor;
	}

	public void setDealRequestWrapper(DealRequestWrapper dealRequestWrapper) {
		this.dealRequestWrapper = dealRequestWrapper;
	}

	public void setChannelStrategyMap(
			Map<String, ChannelResponseParseStrategy> channelStrategyMap) {
		this.channelStrategyMap = channelStrategyMap;
	}

	public ChargeResponse charge(ChargeRequest request) {
		DealRequest drDto = transToDealRequest(request);
		dealRequestWrapper.addRequestParameters(drDto);
		DealRequest dealRequest = dealRequestDao.saveReq(drDto);
		return reissue(dealRequest, InterfaceType.REQUEST.getValue());
	}

	// 将ChargeRequest转换为dealRequest
	private DealRequest transToDealRequest(final ChargeRequest request) {
		DealRequest drDto = new DealRequest();
		drDto.setChannelCode(request.getChannelCode());
		drDto.setCardNo(request.getCardNo());
		drDto.setSeqNo(request.getSeqNo());
		drDto.setCardPwd(request.getCarPwd());
		drDto.setMobileNo(request.getMobileNo());
		drDto.setRequestAmount(request.getChargeAmount());
		drDto.setCreationDate(new Timestamp(System.currentTimeMillis()));
		drDto.setDealAmount(0L);
		drDto.setReissueTimes(1);
		drDto.setStatus(OrderStatus.INIT.getValue());
		drDto.setQueryTimes(0);
		return drDto;
	}

	public ChargeResponse query(DealRequest request) {
		dealRequestWrapper.addQueryParameters(request);
		return reissue(request, InterfaceType.QUERY.getValue());
	}

	public ChargeResponse reissue(DealRequest dealRequest) {
		return reissue(dealRequest, InterfaceType.REQUEST.getValue());
	}

	private ChargeResponse reissue(DealRequest dealRequest, int interfaceType) {
		DealResponse responseDto = channelAccessor.sendRequest(dealRequest);
		// 如果反馈为空直接停止
		if (StringUtil.isEmpty(responseDto.getResContentval())) {
			logger.info("************ channelAccessor.sendRequest retrun null code:"
					+ dealRequest.getChannelCode());
			// 超时处理
			dealRequest.setLastUpdate(new Date());
			dealRequest.setStatus(OrderStatus.TIMEOUT.getValue());
			dealRequestDao.updateRequest(dealRequest);
			return null;
		}
		responseDto.setRequestId(dealRequest.getId());
		// 解析渠道响应--渠道code和内容
		// 设置返回状态和返回码---金额
		String code = dealRequest.getChannelCode();
		ChannelResponseParseStrategy crpStrategy = channelStrategyMap.get(code
				.substring(0, code.indexOf("-")));

		logger.info("************ select ChannelResponseParseStrategy code:"
				+ dealRequest.getChannelCode());

		// 查询的状态 有进行中 没有状态就是 999 代表提交的数据
		crpStrategy.parseResponse(responseDto, interfaceType);
		dealResponseDao.saveResponse(responseDto);
		// 去错误吗关系表查询关系
		ChannelGatewayRelation channelGatewayRelation = channelGatewayRelationDao
				.getGatewayCodeByChannelAndCode(dealRequest.getChannelCode(),
						responseDto.getStatus(), responseDto.getErrorCode());
		// 设置状态
		ChargeResponse response = new ChargeResponse();
		if (channelGatewayRelation == null) {
			logger.info(
					"Callback handler strategy is undefine, respcode is : {},,,{}",
					dealRequest.getChannelCode(), responseDto.getResCode());
		} else {
			// 需要修改
			if (channelGatewayRelation.getStatus() == ResultStatus.SUCC
					.getValue()) {
				dealRequest.setStatus(OrderStatus.SUCC.getValue());
			} else if (channelGatewayRelation.getStatus() == ResultStatus.FAIL
					.getValue()) {
				dealRequest.setStatus(OrderStatus.FAIL.getValue());
			} else if (interfaceType == InterfaceType.QUERY.getValue()) {
				// 如果是查询请求 没有最终结果 就不需要处理
				return response;
			} else {
				dealRequest.setStatus(OrderStatus.ING.getValue());
			}
			dealRequest.setDealAmount(responseDto.getDealAmount());
			dealRequest.setLastUpdate(new Date());
			dealRequestDao.updateRequest(dealRequest);

			response.setChannelCode(dealRequest.getChannelCode());
			response.setErrorCode(channelGatewayRelation.getSystemErrorCode());
			response.setFinishTime(new Date());
			response.setPayMoney(responseDto.getDealAmount());
			response.setSeqNo(dealRequest.getSeqNo());
			response.setStatus(channelGatewayRelation.getStatus());
			response.setStrategyCode(channelGatewayRelation.getStrategyCode()); // 这个状态后续还需要处理的
			// 放到队列中--继续向上更改状态--金额----目前直接更新状态999-- 成功的结算金额到商户表.//结算余额 是否零吞卡等情况
			// 通知商户结果
			commStatusProcess.dispatch(response);
		}
		return response;
	}

	public static void main(String[] args) {
		ChargeServiceImpl l = new ChargeServiceImpl();
		l.setChannelAccessor(new CommChannelAccessor());
		l.setDealRequestWrapper(new CommDealRequestWrapper());

		ChargeRequest request = new ChargeRequest();
		request.setCardNo("1");
		request.setCarPwd("2");
		request.setChannelCode("new6");
		request.setChargeAmount(100L);
		request.setSeqNo("20120916");
		l.charge(request);
	}
}
